package pri.hillchen.std.design.util;

import jdk.nashorn.internal.codegen.CompilerConstants;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

/**
 * Created by hillchen on 2018/3/9.
 * 线程执行工具类
 */
public class ThreadExecutors {
    /**
     * 同时启动执行所用的线程并让主线程等待所有子线执行完成
     * @param runnables
     * @return 返回整个执行过程所用时间
     */
    public static long excuteBySameTimeStartAndWaitEnd(Collection<? extends Runnable> runnables) throws BrokenBarrierException, InterruptedException {
        /**
         * 没有线程可执行直接退出。
         */
        if(runnables==null||runnables.isEmpty()){
            return 0L;
        }
        int threadCount = runnables.size();
        /**
         * 使用CyclicBarrier使所有线程在同一时间点开始执行
         */
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount + 1);
        /**
         * 使用CountDownLatch使主线程等待所有子线程执行结束
         */
        final CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        for(final Runnable runnable : runnables ){
            new Thread(){
                @Override
                public void run() {
                    try {
                        //等待开始命令
                        cyclicBarrier.await();
                        runnable.run();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }finally {
                        //告诉主线程子线程以执行完毕
                        countDownLatch.countDown();
                    }
                }
            }.start();
        }
        long start = System.currentTimeMillis();

        //保证同时开始
        cyclicBarrier.await();
        //保证同时同时结束
        countDownLatch.await();
        long end = System.currentTimeMillis();
        return end - start;
    }

}
